package com.longteng.diamond.service;

import com.alibaba.fastjson.JSON;
import com.longteng.diamond.dao.QuartzMapper;
import com.longteng.diamond.domain.ScheduleJob;
import com.longteng.diamond.job.QuartzJob;
import com.longteng.diamond.util.DateUtil;
import lombok.extern.slf4j.Slf4j;
import org.quartz.*;
import org.quartz.impl.StdSchedulerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;


/**
 * Created by Administrator
 * DATE : 2018/7/22
 * TIME : 22:47
 * PROJECT : java-lesson
 * PACKAGE : com.longteng.lesson
 *
 * @author <a href="mailto:taki@qq.com">Administrator</a>
 */
@Slf4j
@Component
public class QuartzService {

    private static SchedulerFactory gSchedulerFactory = new StdSchedulerFactory();
    public static String JOB_GROUP_NAME = "_JOBGROUP_NAME";
    public static String TRIGGER_GROUP_NAME = "_TRIGGERGROUP_NAME";
    public static String TRIGGER_NAME = "TRIGGER_NAME";

    @Autowired
    private QuartzMapper quartzMapper;

    /**
     * 添加一个定时任务
     *
     * @param scheduleJob
     */
    public void addQuartzJob(ScheduleJob scheduleJob) {
        Integer testPlanId = scheduleJob.getTestPlanId();
        String testPlanName = scheduleJob.getTestPlanName();
        /**
         * 通过计划id+计划名称组成一个定时任务
         * **/
        scheduleJob.setJobName(testPlanId + testPlanName);

        List<String> weekTimeList = (List) JSON.parseArray(scheduleJob.getWeekTimeList());
        //0 15 18 0 0 1,4,5
        String jobTime = this.getWeekTime(weekTimeList, scheduleJob.getHhTime(), scheduleJob.getMmTime());
        /**
         * 添加表达式时间放到定时任务的job里面去
         * **/
        this.addJob(scheduleJob, QuartzJob.class, jobTime);
        quartzMapper.addScheduleJob(scheduleJob);
//        "0/1 * * * * ?"
    }

    /**
     * 添加一个定时任务
     *
     * @param scheduleJob
     * @param jobClass    任务
     * @param time        时间设置，参考quartz说明文档
     */
    @SuppressWarnings("unchecked")
    public void addJob(ScheduleJob scheduleJob, Class jobClass,
                       String time) {
        try {
            log.info("创建定时任务");
            Scheduler scheduler = gSchedulerFactory.getScheduler();
            if (!scheduler.isStarted()) {
                // 开启调度器
                scheduler.start();
            }
            String jobName = scheduleJob.getJobName();
            String jobGroupName = jobName + QuartzService.JOB_GROUP_NAME;
            /**
             * 新增一个任务,并且需要一个执行类
             * 真正执行任务的时候需要有一个类被触发出行
             * QuartzJob是目标对象
             * **/
            JobDetail jobDetail = JobBuilder.newJob(jobClass)
                    .withIdentity(jobName, jobGroupName).build();
            jobDetail.getJobDataMap().put("scheduleJob", scheduleJob);

            String triggerName = jobName + QuartzService.TRIGGER_NAME;
            String triggerGroupName = jobName + QuartzService.TRIGGER_GROUP_NAME;
            /**
             * 设置时间表达式
             * 设置触发器
             * **/
            CronScheduleBuilder scheduleBuilder = CronScheduleBuilder.cronSchedule(time);
            // 触发器名,触发器组
            Trigger trigger = org.quartz.TriggerBuilder.newTrigger()
                    .withIdentity(triggerName, triggerGroupName)
                    .startNow()
                    .withSchedule(scheduleBuilder)
                    .build();
            try {
                scheduler.scheduleJob(jobDetail, trigger);
            } catch (SchedulerException e) {
                log.error("注册任务和触发器失败", e);
            }
            log.info("定时任务启动完毕!");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * 删除定时任务
     *
     * @param id
     */
    public void deleteQuartzJobById(Integer id) {
        ScheduleJob scheduleJob = quartzMapper.findScheduleJobById(id);
        String jobName = scheduleJob.getJobName();
        String jobGroupName = jobName + QuartzService.JOB_GROUP_NAME;
        String triggerName = jobName + QuartzService.TRIGGER_NAME;
        String triggerGroupName = jobName + QuartzService.TRIGGER_GROUP_NAME;
        this.removeJob(jobName, jobGroupName, triggerName, triggerGroupName);
        quartzMapper.deleteScheduleJobById(id);
    }

    /**
     * 获取时间表达式
     *
     * @param weekTimeList
     * @param hhTime
     * @param mmTime
     */
    public String getWeekTime(List<String> weekTimeList, int hhTime, int mmTime) {
        String w = "";
        for (int i = 0; i < weekTimeList.size(); i++) {
            /**
             * 获取星期几的英文缩写
             * **/
            String e = DateUtil.getEnWeekByNum(Integer.parseInt(weekTimeList.get(i)));
            if (i == weekTimeList.size() - 1) {
                w = w + e;
            } else {
                w = w + e + ",";
            }
        }
        //0 12 11 ? * MON
        String jobTime = "0 " + mmTime + " " + hhTime + " ? * " + w;
        log.info("job时间:" + jobTime);
        return jobTime;
    }

    /**
     * 修改定时任务
     *
     * @param scheduleJob
     */
    public void modifyQuartzJob(ScheduleJob scheduleJob) {
        String jobName =scheduleJob.getTestPlanId()+scheduleJob.getTestPlanName();
        scheduleJob.setJobName(jobName);
        List<ScheduleJob> scheduleJobs=quartzMapper.findQuartz(scheduleJob);
        if(!CollectionUtils.isEmpty(scheduleJobs)){
            ScheduleJob dbScheduleJob =scheduleJobs.get(0);
            String dbJobName= dbScheduleJob.getJobName();
            String jobGroupName = dbJobName + QuartzService.JOB_GROUP_NAME;
            String triggerName = dbJobName + QuartzService.TRIGGER_NAME;
            String triggerGroupName = dbJobName + QuartzService.TRIGGER_GROUP_NAME;
            this.removeJob(dbJobName, jobGroupName, triggerName, triggerGroupName);
            scheduleJob.setId(dbScheduleJob.getId());
            quartzMapper.updateScheduleJob(scheduleJob);
        }else {
            quartzMapper.addScheduleJob(scheduleJob);
        }
        List<String> weekTimeList = (List) JSON.parseObject(scheduleJob.getWeekTimeList(),List.class);
        String jobTime = this.getWeekTime(weekTimeList, scheduleJob.getHhTime(), scheduleJob.getMmTime());
        this.addJob(scheduleJob, QuartzJob.class, jobTime);
    }

    /**
     * 获取job明细
     *
     * @param scheduleJob
     */
    public JobDetail getJobDetail(ScheduleJob scheduleJob) {
        JobDetail jobDetail = null;
        try {
            Scheduler scheduler = gSchedulerFactory.getScheduler();
            String jobName = scheduleJob.getJobName();
            String jobGroupName = jobName + QuartzService.JOB_GROUP_NAME;
            JobKey jobKey = new JobKey(jobName, jobGroupName);
            jobDetail = scheduler.getJobDetail(jobKey);
        } catch (SchedulerException e) {
            log.error("获取定时任务明细错误", e);
        }
        return jobDetail;
    }

    /**
     * 获取Trigger明细
     *
     * @param scheduleJob
     */
    public Trigger getTrigger(ScheduleJob scheduleJob) {
        Trigger trigger = null;
        try {
            Scheduler scheduler = gSchedulerFactory.getScheduler();
            String jobName = scheduleJob.getJobName();
            String triggerName = jobName + QuartzService.TRIGGER_NAME;
            String triggerGroupName = jobName + QuartzService.TRIGGER_GROUP_NAME;
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
            trigger = scheduler.getTrigger(triggerKey);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return trigger;
    }

    /**
     * 移除一个任务
     *
     * @param jobName
     * @param jobGroupName
     * @param triggerName
     * @param triggerGroupName
     */
    public void removeJob(String jobName, String jobGroupName,
                          String triggerName, String triggerGroupName) {
        try {
            log.info("定时任务删除开始!");
            Scheduler scheduler = gSchedulerFactory.getScheduler();
            // 停止触发器
            TriggerKey triggerKey = new TriggerKey(triggerName, triggerGroupName);
            scheduler.pauseTrigger(triggerKey);
            // 移除触发器
            scheduler.unscheduleJob(triggerKey);
            // 删除任务
            JobKey jobKey = new JobKey(jobName, jobGroupName);
            scheduler.deleteJob(jobKey);
            log.info("定时任务删除完毕!");
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
}
